#include "StdAfx.h"
#include "ACMSimpleGAB2D.h"

float ACMSimpleGAB2D::Objective(GAGenome& g)
{
	GABin2DecGenome& genome = (GABin2DecGenome &) g;
	vector<double> paras;
	for (int i = 0; i < genome.nPhenotypes(); i++)
	{
		paras.push_back(genome.phenotype(i));
	}
	AttachedData* adata = (AttachedData*) g.userData();
	adata->mp_model->number();
	adata->mp_model->parameters(paras);
	vector<double> SimRunoff = adata->mp_model->runoff(
		adata->rainfall
		);

	// TO DO coe should be replaceable
	return coe(SimRunoff, adata->ObsRunoff);
}

ACMSimpleGAB2D::ACMSimpleGAB2D(void):mp_GA(0), mp_Genome(0)
{
}
ACMSimpleGAB2D::~ACMSimpleGAB2D(void)
{
	if (mp_GA)
		delete mp_GA;
	if (mp_Genome)
		delete mp_Genome;
}
const vector<double>
ACMSimpleGAB2D::bestIndividual()
{
	GABin2DecGenome genome = (const GABin2DecGenome&) 
		(mp_GA->statistics().bestIndividual());
	std::vector<double> paras;
	paras.clear();
	for (int i = 0 ; i<genome.nPhenotypes(); i++)
	{
		paras.push_back(
			genome.phenotype(i)
			);
	}
	return paras;
}

void ACMSimpleGAB2D::configure(const vector<const GenomeType*>& info,
		pEval eval)
{
	m_eval = eval;
	for (unsigned int i = 0; i < info.size(); i++)
	{
		m_Phenotype.add(
			info[i]->length(),
			info[i]->lower(),
			info[i]->upper()
			);
	}
}
void
ACMSimpleGAB2D::evolve()
{
	mp_GA->evolve();
}

const ACMSimpleGAB2D::pEval
ACMSimpleGAB2D::eval() const
{
	return m_eval;
}

void
ACMSimpleGAB2D::initialize()
{

	mp_Genome = new GABin2DecGenome(m_Phenotype,
		Objective, (void*) &m_Adata);
	mp_GA = new GASimpleGA(*mp_Genome);
	mp_GA->scaling(m_Scaling);
	mp_GA->scoreFilename(fileName.c_str());
	mp_GA->flushFrequency(50);
	mp_GA->selectScores(GAStatistics::AllScores);
	mp_GA->elitist(gaTrue);
}
// for testing the GASimpleGA
#ifdef _GASIMPLEGA_TEST
void 
ACMSimpleGAB2D::phenotype()
{
	float min[] = {0, 0,   3, -5, 100,    0.001, 0};
	float max[] = {1, 100, 3, -2, 100000, 0.010, 7};
	for(int i=0; i<7; i++)
    m_Phenotype.add(8, min[i], max[i]);
}
void 
ACMSimpleGAB2D::userData(float* p)
{
	mp_userData = p;
}
#endif
void 
ACMSimpleGAB2D::maximize()
{
	mp_GA->maximize();
}

void 
ACMSimpleGAB2D::minimize()
{
	mp_GA->minimize();
}

const unsigned int
ACMSimpleGAB2D::nPopulation() const
{
	return mp_GA->populationSize();
}
void
ACMSimpleGAB2D::nPopulation(const unsigned int& n)
{
	mp_GA->populationSize(n);
}

const unsigned int ACMSimpleGAB2D::nGeneration() const
{
	return mp_GA->nGenerations();
}

void 
ACMSimpleGAB2D::nGeneration(const unsigned int& n)
{
	mp_GA->nGenerations(n);
}

const double
ACMSimpleGAB2D::pMutation() const
{
	return mp_GA->pMutation();
}

void
ACMSimpleGAB2D::pMutation(const double& p)
{
	mp_GA->pMutation(p);
}

const double ACMSimpleGAB2D::pCrossover() const
{
	return mp_GA->pCrossover();
}
void
ACMSimpleGAB2D::pCrossover(const double& p)
{
	mp_GA->pCrossover(p);
}


void ACMSimpleGAB2D::model(NCUCModel* p)
{
	m_Adata.mp_model = p;
}

void ACMSimpleGAB2D::obsRunoff(const vector<double>& obs)
{
	m_Adata.ObsRunoff.clear();
	m_Adata.ObsRunoff.assign(obs.begin(), obs.end());
}

void ACMSimpleGAB2D::rainfall(const vector<double>& p)
{
	m_Adata.rainfall.clear();
	m_Adata.rainfall.assign(p.begin(), p.end());
}
/*ACMSimpleGAB2D& ACMSimpleGAB2D::operator=(const ACMSimpleGAB2D& rhs)
{
	rhs.m_eval = m_eval;
	rhs.m_phenotype = m_phenotype;
	rhs.mp_ga = mp_ga->c
*/
